package client.zookeeper;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.ServiceLoader;
import java.util.Set;

import org.apache.log4j.Logger;

import core.AlertUtil;
import core.TextAreaAppender;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeView;

public class ZookeeperClientController implements Initializable{
		
	/**
	 * Zookeeper客户端名称与实例的Map集合
	 */
	private static final Map<String,IZookeeperClient> ZOOKEEPER_CLIENT=new HashMap<String,IZookeeperClient>();
	static {
		//通过服务发现查找Zookeeper客户端实例
		ServiceLoader<IZookeeperClient> clients=ServiceLoader.load(IZookeeperClient.class);
		for(IZookeeperClient client:clients) {
			ZOOKEEPER_CLIENT.put(client.getName(), client);
		}
	}
	
	//应用日志对象
	private Logger appLogger;
	
	/**
	 * 左侧树结构
	 */
	@FXML
	private TreeView<ZookeeperTreeNode> zkTreeView;

	/**
	 * 信息组件
	 */
	@FXML
	private TextArea infoTextArea;
	
	/**
	 * 命令历史组件
	 */
	@FXML
	private TextArea cmdTextArea;
	
	/**
	 * 命令输入框
	 */
	@FXML
	private TextField cmdTextField;
	
	/**
	 * 日志组件
	 */
	@FXML
	private TextArea logTextArea;

	/**
	 * zookeeper客户端连接实例
	 */
	private IZookeeperClient zookeeperClient;
	
	@Override
	public void initialize(URL location, ResourceBundle resources) {
		appLogger = Logger.getLogger("zookeeper_client_app");
		appLogger.addAppender(new TextAreaAppender(logTextArea));
		appLogger.info("日志输出初始化完成！");
	}
	
	/**
	 * 选择zookeeper客户端。
	 * 如果只有一个实例则直接使用，多个时弹出选择对话框进行选择。
	 * @return
	 */
	private IZookeeperClient choiceClient() {
		appLogger.info("进行客户端选择。");
		if(ZOOKEEPER_CLIENT.size() == 1) {
			appLogger.info("仅有一个客户端示例，无需选择！");
			//只有一种客户端
			for(IZookeeperClient client:ZOOKEEPER_CLIENT.values()) {
				return client;
			}
		}
		
		appLogger.info("启动客户端选择对话框。");
		//弹出选择对话框进行选择
		Set<String> clients = ZOOKEEPER_CLIENT.keySet();
		Optional<String> result = AlertUtil.choice("选择客户端", "请选择连接客户端类型：", clients);
		if(result.isPresent()) {
			appLogger.info("用户选择客户端："+result.get());
			return ZOOKEEPER_CLIENT.get(result.get());
		}
		
		return null;
	}
	
	/**
	 * 新建连接按钮监听
	 * @param e	事件对象
	 * @throws IOException　zookeeper连接操作可能发生异常
	 */
	public void createConnection(ActionEvent e) throws IOException{
		appLogger.info("检查是否存在已连接的客户端。");
		//如果zookeeper客户端实例不为空则先关闭之前的连接
		if(zookeeperClient != null) {
			appLogger.info("关闭已连接的客户端。");
			zookeeperClient.close();
		}
		
		//选择zookeeper客户端
		this.zookeeperClient = this.choiceClient();
		if(zookeeperClient != null) {
			//初始化zookeeper连接和组件
			zookeeperClient.init(this);
		}
	}
	
	/**
	 * 执行命令动作监听
	 * @param e　事件对象
	 */
	public void exeCmd(ActionEvent e) {
		if(zookeeperClient == null) {
			appLogger.error("无法执行用户输入命令！【未建立连接】");
			return;
		}
		
		String cmdStr = cmdTextField.getText();
		if(cmdStr == null || "".equals(cmdStr.trim())) {
			appLogger.error("无法执行用户输入命令！【命令为空】");
			return;
		}
		
		appLogger.info("执行用户输入命令："+cmdStr);
		//执行zookeeper命令
		String result = zookeeperClient.exeCmd(cmdStr);
		//清空命令输入框
		cmdTextField.clear();
		//将命令和响应追加到命令执行历史内
		cmdTextArea.appendText("> "+cmdStr+"\n");
		if(result!=null) {
			cmdTextArea.appendText(result+"\n");
		}
	}

	public TreeView<ZookeeperTreeNode> getZkTreeView() {
		return zkTreeView;
	}

	public TextArea getInfoTextArea() {
		return infoTextArea;
	}

	public TextArea getCmdTextArea() {
		return cmdTextArea;
	}

	public TextField getCmdTextField() {
		return cmdTextField;
	}

	public Logger getAppLogger() {
		return appLogger;
	}
}
